package com.fecean.aabbc.netty.server.prod7;

import com.fecean.aabbc.netty.handler7.NettyNoticeChannelHandler;
import com.fecean.aabbc.netty.handler7.NettyRequestChannelHandler;
import com.fecean.aabbc.netty.handler7.NettyResponseChannelHandler;
import com.fecean.aabbc.netty.message7.GoogleProtobuf;
import com.fecean.aabbc.netty.ssl.SSLEngineFactory;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.ssl.SslHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;

/**
 ** Netty服务端通道初始化
 *
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-03-10 10:53
 * @blame Team
 */
@Component
@ChannelHandler.Sharable
public class NettyServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    /**
     ** 注册通道处理
     */
    @Resource
    NettyServerRegisterHandler nettyServerRegisterHandler;

    /**
     ** 心跳通道处理
     */
    @Resource
    NettyServerHeartbeatHandler nettyServerHeartbeatHandler;

    /**
     ** 通知通道处理
     */
    @Resource
    NettyNoticeChannelHandler nettyNoticeChannelHandler;

    /**
     ** 请求通道处理
     */
    @Resource
    NettyRequestChannelHandler nettyRequestChannelHandler;

    /**
     ** 响应通道处理
     */
    @Resource
    NettyResponseChannelHandler nettyResponseChannelHandler;



    /**
     ** 初始化通道处理器
     * @param channel channel
     */
    @Override
    protected void initChannel(SocketChannel channel) throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext context = SSLContext.getInstance(SSLEngineFactory.PROTOCOL_TLS);
        KeyManagerFactory keyManagerFactory = SSLEngineFactory.getKeyManagerFactory("cert/server.p12", "123456", "123456");
        TrustManagerFactory trustManagerFactory = SSLEngineFactory.getTrustManagerFactory("cert/root.p12", "123456");
        context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
        SSLEngine sslEngine = context.createSSLEngine();
        sslEngine.setUseClientMode(false);
        sslEngine.setNeedClientAuth(true);
        channel.pipeline().addFirst("ssl", new SslHandler(sslEngine));

        // 添加编码解码处理：实体类传输数据，protobuf序列化
        channel.pipeline().addLast(new ProtobufVarint32FrameDecoder());
        channel.pipeline().addLast(new ProtobufDecoder(GoogleProtobuf.DataObject.getDefaultInstance()));
        channel.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
        channel.pipeline().addLast(new ProtobufEncoder());
        // 添加注册通道处理
        channel.pipeline().addLast(nettyServerRegisterHandler);
        // 添加心跳通道处理
        channel.pipeline().addLast(nettyServerHeartbeatHandler);
        // 添加通知通道处理
        channel.pipeline().addLast(nettyNoticeChannelHandler);
        // 添加请求通道处理
        channel.pipeline().addLast(nettyRequestChannelHandler);
        // 添加响应通道处理
        channel.pipeline().addLast(nettyResponseChannelHandler);
    }
}
